﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Google.YouTube;
using Google.GData.Client;
using System.Diagnostics;

namespace YoutubeGetter
{
    public partial class MainForm : Form
    {
        private List<Video> videos = new List<Video>();
		private BackgroundWorker fetcher = new BackgroundWorker();
		private Label loadingText;
		private String activeCategory;
        public MainForm()
        {
            InitializeComponent();
			fetcher.DoWork += new DoWorkEventHandler(fetcher_DoWork);
			fetcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(fetcher_RunWorkerCompleted);

			loadingText = new Label();
			loadingText.Text = "Fetching videos from youtube, please wait...";
			loadingText.BackColor = pnlVideos.BackColor;
			loadingText.Width = 320;
			loadingText.Location = new Point(75, 100);
			loadingText.Font = new Font("Verdana", 10f);
			pnlVideos.Controls.Add(loadingText);
			loadingText.Visible = false;
        }

        private void tbnLogin_Click(object sender, EventArgs e)
        {
            LoginForm loginForm = new LoginForm();
            loginForm.ShowDialog();
            if (loginForm.isLoggedIn)
            {
                FillSideBar();
            }
        }
		private void tvFolders_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			if (!fetcher.IsBusy && e.Node.Tag != null)
			{
                tvFolders.Enabled = false;
				videos.Clear();
				RemoveVideos();
				loadingText.Visible = true;
				fetcher.RunWorkerAsync(e.Node);
			}
		}
		private void fetcher_DoWork(object sender, DoWorkEventArgs e)
		{
			Feed<Video> videoCache;
			switch (((TreeNode)e.Argument).Tag.ToString())
			{
				case "MYVIDEOS":
					videoCache = YoutubeTools.request.GetVideoFeed(YoutubeTools.request.Settings.Credentials.Username);
					videoCache.AutoPaging = true;
					foreach (Video video in videoCache.Entries)
					{
						if (video.Thumbnails.Count > 0) // checking thumbnails is one way of verifying that the video is actually valid
						{
							videos.Add(video);
						}
					}
					activeCategory = "My Videos";
					break;
				case "MYFAVORITES":
					videoCache = YoutubeTools.request.GetFavoriteFeed(YoutubeTools.request.Settings.Credentials.Username);
					videoCache.AutoPaging = true;
					foreach (Video video in videoCache.Entries)
					{
						if (video.Thumbnails.Count > 0)
						{
							videos.Add(video);
						}
					}
					activeCategory = "My Favorites";
					break;
				default:
					if (((TreeNode)e.Argument).Tag.GetType() == typeof(Playlist))
					{
						Playlist selectedPlaylist = (Playlist)((TreeNode)e.Argument).Tag;
						Feed<PlayListMember> members = YoutubeTools.request.GetPlaylist(selectedPlaylist);
                        members.AutoPaging = true;
						foreach (PlayListMember member in members.Entries)
						{
							try
							{
								Video video = YoutubeTools.request.Retrieve<Video>(new Uri(String.Format(YoutubeTools.videoUrlID, member.VideoId)));
								videos.Add(video);
							}
							catch
							{
								// The Retrieve command simply throws an error if the requested video no longer exists
								// Why does youtube show non existing videos in their playlists anyway? :/
							}
						}
						activeCategory = "Playlists\\" + selectedPlaylist.Title;
					}
                    //if (((TreeNode)e.Argument).Tag.GetType() == typeof(Subscription))
                    //{
                    //    Subscription selectedSubscription = (Subscription)((TreeNode)e.Argument).Tag;
                    //    foreach (PlayListMember member in members.Entries)
                    //    {
                    //        try
                    //        {
                    //            Video video = YoutubeTools.request.Retrieve<Video>(new Uri(String.Format(YoutubeTools.videoUrlID, member.VideoId)));
                    //            videos.Add(video);
                    //        }
                    //        catch
                    //        {
                    //            // The Retrieve command simply throws an error if the requested video no longer exists
                    //            // Why does youtube show non existing videos in their playlists anyway? :/
                    //        }
                    //    }
                    //    activeCategory = "Playlists\\" + selectedSubscription.Title;
                    //}
					break;
			}
		}
		private void fetcher_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			loadingText.Visible = false;
            tvFolders.Enabled = true;
			PopulateVideos();
		}
		private void video_DoubleClick(object sender, EventArgs e)
		{
			String browser = "";
			Process BrowserProcess = new Process();
			ProcessStartInfo BrowserParams = new ProcessStartInfo();
			BrowserParams.UseShellExecute = true;

			Microsoft.Win32.RegistryKey key = null;
			try
			{
				key = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(@"http\\shell\\open\\command", false);

				//trim off quotes
				browser = key.GetValue(null).ToString().ToLower().TrimStart("\\\"".ToCharArray());
				if (!browser.EndsWith("exe"))
				{
					//get rid of everything after the ".exe"
					browser = browser.Substring(0, browser.LastIndexOf(".exe") + 4);
				}
			}
			catch // something went wrong while trying to find the default browser, just return IE
			{
				browser = "iexplore.exe";
			}

			BrowserParams.FileName = browser;
			BrowserParams.Arguments = " " + ((VideoControl)sender).video.WatchPage;
			BrowserProcess.StartInfo = BrowserParams;
			BrowserProcess.Start();
		}
		private void PopulateVideos()
		{
			foreach (Video video in videos)
			{
				AddVideoToList(video);
			}
		}

        private void FillSideBar()
        {
            try
            {
                tvFolders.Nodes.Clear();
                // root node
                TreeNode mainNode = new TreeNode(YoutubeTools.request.Settings.Credentials.Username);
				mainNode.BackColor = Color.LightGray;
                mainNode.Tag = "";
                TreeNode subNode;
                // "my videos" node
                subNode = new TreeNode("My videos");
                subNode.Tag = "MYVIDEOS";
                mainNode.Nodes.Add(subNode);
                // "my favorites" node
                subNode = new TreeNode("My favorites");
                subNode.Tag = "MYFAVORITES";
                mainNode.Nodes.Add(subNode);
                // "my playlists" node
                subNode = new TreeNode("My playlists");
                TreeNode playListNode;
                Feed<Playlist> playLists = YoutubeTools.request.GetPlaylistsFeed(YoutubeTools.request.Settings.Credentials.Username);
                foreach (Playlist playList in playLists.Entries)
                {
                    playListNode = new TreeNode(playList.Title);
					playListNode.Tag = playList;
                    subNode.Nodes.Add(playListNode);
                }
                mainNode.Nodes.Add(subNode);
                // "my subscriptions" node
                subNode = new TreeNode("My subscriptions");
                TreeNode subscriptionNode;
                Feed<Subscription> subscriptions = YoutubeTools.request.GetSubscriptionsFeed(YoutubeTools.request.Settings.Credentials.Username);
                foreach (Subscription subscription in subscriptions.Entries)
                {
                    subscriptionNode = new TreeNode(subscription.Title);
                    subscriptionNode.Tag = subscription;
                    subNode.Nodes.Add(subscriptionNode);
                }
                mainNode.Nodes.Add(subNode);
                tvFolders.Nodes.Add(mainNode);
            }
            catch (Exception ex)
            {
                if (ex.GetType() == typeof(InvalidCredentialsException))
                {
                    tvFolders.Nodes.Clear();
                    MessageBox.Show("Could not login to youtube. Invalid password?");
                }
                else
                {
                    throw ex;
                }
            }
        }
		private void RemoveVideos()
		{
			List<Control> controlsToRemove = new List<Control>();
			foreach (Control control in pnlVideos.Controls)
			{
				if (control.GetType() == typeof(VideoControl))
				{
					controlsToRemove.Add(control);
				}
			}
			foreach (Control control in controlsToRemove)
			{
				pnlVideos.Controls.Remove(control);
			}
		}
        private void AddVideoToList(Video video)
        {
            VideoControl control = new VideoControl(video);
			control.DoubleClick += new EventHandler(video_DoubleClick);
			control.Dock = DockStyle.Top;
			control.Margin = new Padding(0, 0, 0, 3);
            pnlVideos.Controls.Add(control);
        }

		private void PerformAction(object sender, EventArgs e)
		{
			String senderName;
			if (sender.GetType() == typeof(ToolStripButton))
			{
				senderName = ((ToolStripButton)sender).Name;
			}
			else
			{
				senderName = ((Control)sender).Name;
			}
			foreach (Control control in pnlVideos.Controls)
			{
				if (control.GetType() == typeof(VideoControl))
				{
					
					switch (senderName.ToUpper())
					{
						case "LLSELECTALL":
							((VideoControl)control).isSelected = true;
							break;
						case "LLSELECTNONE":
							((VideoControl)control).isSelected = false;
							break;
						case "TBNDOWNLOAD":
							if (((VideoControl)control).isSelected && ((VideoControl)control).Enabled == true)
							{
								((VideoControl)control).DownloadVideo(activeCategory);
							}
							break;
					}
				}
			}
		}

		private void tbnSettings_Click(object sender, EventArgs e)
		{
			SettingsForm form = new SettingsForm();
			form.ShowDialog();
		}
    }
}
